package com.lsh.oms.worker.service.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lsh.base.common.utils.CollectionUtils;
import com.lsh.oms.core.constant.ReturnCode;
import com.lsh.oms.core.email.SendEmailService;
import com.lsh.oms.core.enums.StraType;
import com.lsh.oms.core.enums.StrategyRequestAttrType;
import com.lsh.oms.core.exception.BusinessException;
import com.lsh.oms.core.model.order.OrderHead;
import com.lsh.oms.core.proxy.model.Position;
import com.lsh.oms.core.proxy.model.strategy.*;
import com.lsh.oms.core.proxy.model.user.AddressInfo;
import com.lsh.oms.core.proxy.model.user.UserContent;
import com.lsh.oms.core.proxy.model.user.UserInfo;
import com.lsh.oms.core.proxy.service.AtpProxy;
import com.lsh.oms.core.proxy.service.GaoDeProxy;
import com.lsh.oms.core.proxy.service.StrategyProxy;
import com.lsh.oms.core.proxy.service.WgServiceProxy;
import com.lsh.oms.core.redis.RedisTemplate;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Project Name: OrderCommit2OfcService
 * 北京链商电子商务有限公司
 *
 * @author peter
 * Date: 19/2/18
 * Package Name: com.lsh.oms.worker.service.service
 * Description:
 */
@Service
public class OrderCommit2OfcService {
    private static final Logger logger = LoggerFactory.getLogger(OrderCommit2OfcService.class);
    private static final String FENCE_ID_PREWAREHOUSE_CODE_MAPPING = "FENCE_ID_PREWAREHOUSE_CODE_MAPPING";

    @Autowired
    private AtpProxy atpProxy;

    @Autowired
    private GaoDeProxy gaoDeProxy;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private StrategyProxy strategyProxy;

    @Autowired
    private WgServiceProxy wgServiceProxy;

    @Autowired
    private SendEmailService sendEmailService;

    @Value("${shopUrl}")
    private String shopUrl;

    /**
     * 判断订单，是否下发OFC
     *
     * @param logSign
     * @param head
     * @return
     */
    public boolean isCommitOfc(String logSign, OrderHead head, String orderDc, UserContent userContent, Map<String, Object> fenceInfo) {
        Long addressId = head.getAddressCode();
        String fenceId = (String) fenceInfo.get("fence_id");

        UserInfo userInfo = userContent.getUserInfo();
        AddressInfo addressInfo = userContent.getAddressInfo();
        if (null == userInfo || null == addressInfo) {
            logger.info("{} 地址id [{}],请求商城用户信息异常,userInfo or addressInfo 不存在", logSign, addressId);
            return false;
        }

        if (StringUtils.isEmpty(orderDc)) {
            return false;
        }

        // 构建请求策略服务的属性集合
        List<StrategyAttr> straAttrValues = new ArrayList<>();
        straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.ZONE_CODE, String.valueOf(head.getRegionCode())));
        straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.USER_ID, userInfo.getUid()));
        straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.USER_TYPE, userInfo.getType()));
        straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.STORAGE_TYPE, head.getStorageType().toString()));
        straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.DC, orderDc));

        // todo: 某个围栏，不下发ofc
        if (!StringUtils.isEmpty(fenceId)) {
            straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.RAIL, fenceId));
        }

        //调用策略服务 策略信息
        StrategyRequest request = new StrategyRequest();
        request.setChannelId(1);
        request.setStraType(StraType.STRA_ORDER_COMMIT.getCode());
        request.setStraAttrValues(straAttrValues);

        try {
            List<StrategyInfo> strategyInfos = strategyProxy.queryStraInfo(request);
            if (CollectionUtils.isEmpty(strategyInfos)) {
                logger.info("{}策略返回为空", logSign);
                return false;
            }

            Collections.sort(strategyInfos);
            logger.info("{}订单是否提交ofc，策略结果：{}", logSign, JSON.toJSONString(strategyInfos.get(0)));
            Integer operateType = strategyInfos.get(0).getStraAttrInfo().getOperateType();
            if (operateType == null || operateType.intValue() == 0) {
                logger.info("{} 是否下发OFC，【订单下发策略】策略返回结果：{}", logSign, operateType);
                return false;
            }
        } catch (BusinessException e) {
            return false;
        }

        return true;
    }

    /**
     * 请求策略服务，获取订单的物流模式
     *
     * @param logSign
     * @param head
     * @return
     */
    public Integer obtainOrderLogisticsMode(String logSign, OrderHead head, JSONObject addressInfo, UserContent userContent1, Position position, Map<String, Object> fenceInfo,String supplierGroup) {
//        UserInfo userInfo = userContent.getUserInfo();
//        String fenceId = String.valueOf(fenceInfo.get("fence_id"));
        JSONObject extJson = JSON.parseObject(head.getExt());
        String orderDc = extJson.getString("orderDc");
        String providerId = extJson.getString("providerId");

        if (StringUtils.isEmpty(orderDc)) {
            throw new BusinessException(ReturnCode.REQUEST_FAIL, "ext中，orderDc不能为空");
        }

        if (StringUtils.isEmpty(providerId)) {
            throw new BusinessException(ReturnCode.REQUEST_FAIL, "ext中，providerId不能为空");
        }

        // 查询GPS信息，获取距离，用于判断是否大于5Km todo:围栏坐标
        // 默认值，给10000Km
//        double distance = 10000000D;
//        String centerPoint = (String) fenceInfo.get("center_point");
//        if (StringUtils.isNotEmpty(centerPoint)) {
//            JSONArray jsonArray = JSON.parseArray(centerPoint);
//            if (jsonArray != null && jsonArray.size() == 2) {
//                Double storeLng = jsonArray.getDouble(0);
//                Double storeLat = jsonArray.getDouble(1);
//                distance = this.gaoDeProxy.getDistance(Double.valueOf(position.getLng()), Double.valueOf(position.getLat()), storeLng, storeLat);
//            }
//        }

//        logger.info("{} 计算门店到商家的距离：{}米", logSign, new BigDecimal(distance).toString());
        // 查询PSI，获取订单重量，用于判断是否大于50Kg
        double distance = 10000000D;
        Double orderWeight = this.getOrderWeight(head);

//        String userGroupIds = addressInfo.getString("user_group_ids");
//        List<Integer> orderUserGroupIds = JSON.parseArray(userGroupIds, Integer.class);
        // 构建请求策略服务的属性集合
        List<StrategyAttr> straAttrValues = new ArrayList<>();
        straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.ZONE_CODE, String.valueOf(head.getRegionCode())));
        straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.USER_TYPE, "0"));
        straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.WEIGHT, String.valueOf(orderWeight)));
        straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.DISTANCE, String.valueOf(distance / 1000)));
        straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.DC, orderDc));
        straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.SUPPLY_MARKET,providerId));
        straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.SUPPLIER_GROUP,supplierGroup));
//        if (StringUtils.isNotEmpty(fenceId)) {
//            straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.RAIL, fenceId));
//        }
//        if (orderUserGroupIds != null && !orderUserGroupIds.isEmpty()) {
//            straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.USER_GROUP, JSON.toJSONString(orderUserGroupIds)));
//        }

        //调用策略服务 策略信息
        StrategyRequest request = new StrategyRequest();
        request.setChannelId(1);
        request.setStraType(StraType.STRA_DELIVERY.getCode());
        request.setStraAttrValues(straAttrValues);

        try {
            List<StrategyInfo> strategyInfos = strategyProxy.queryStraInfo(request);
            if (CollectionUtils.isEmpty(strategyInfos)) {
                logger.info("{}, 【订单配送策略】策略返回结果为空");
                throw new BusinessException(ReturnCode.REQUEST_FAIL, "查询策略服务，配送模式，策略返回结果为空");
            }

            // 按权重排序
            Collections.sort(strategyInfos);
            StraAttrInfo straAttrInfo = strategyInfos.get(0).getStraAttrInfo();
//            Integer operateType = straAttrInfo.getOperateType();
            Integer logisticsMode = straAttrInfo.getLogisticsMode();

            if (logisticsMode == null) {
                throw new BusinessException(ReturnCode.REQUEST_FAIL, "查询策略服务，对应的物流模式，为null");
            }
            logger.info("{}策略服务，物流模式：{}", logSign, logisticsMode);
            return logisticsMode;

            // todo: 如果是前置仓配送，则执行下面的代码！
//            String preWarehouseCode = addressInfo.getString("pre_warehouse_code");
//            Integer deliveryWay = addressInfo.getInteger("delivery_way");
//            if (operateType == null || operateType.intValue() == 0) {
//                // 如果，策略返回 非前置仓配送；则校验商城数据，是否是前置仓配送；如果不一致，则报错
//                if (StringUtils.isNotEmpty(preWarehouseCode) && !"0".equals(preWarehouseCode)
//                        && deliveryWay != null && deliveryWay.intValue() != 1
//                        && (CollectionUtils.isNotEmpty(orderUserGroupIds) || orderWeight.compareTo(Double.valueOf(50)) < 0)) {
//                    String content = new StringBuilder("订单号：").append(head.getOrderCode())
//                            .append("\n订单重量：").append(orderWeight).append("\n用户组信息：").append(userGroupIds).append("\n")
//                            .append("配送模式和商城不一致，商城 pre_warehouse_code：").append(preWarehouseCode).append("，delivery_way：").append(deliveryWay)
//                            .append(", 策略服务（物流模式）：").append(logisticsMode).toString();
//                    sendEmailService.asyncSendEmail(content, "[oms]订单提交OFC,数据一致性问题-" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()), new String[]{"wangliutao@lsh123.com"});
//                    throw new BusinessException(ReturnCode.REQUEST_FAIL, content);
//                }
//                logger.info("{}，【订单配送策略】非前置仓配送！结果：{}", logSign, JSON.toJSONString(straAttrInfo));
//                return logisticsMode;
//            }

//            StraAttrResponse straAttrResponse = strategyProxy.queryStraAttrInfo(StrategyRequestAttrType.RAIL.getCode(), fenceId);
//            if (straAttrResponse == null) {
//                throw new BusinessException(ReturnCode.REQUEST_FAIL, "查询围栏对应的前置仓信息，为null");
//            }
//
//            String straPreWarehouseCode = null;
//            JSONObject attrExt = JSON.parseObject(straAttrResponse.getExt());
//            if (attrExt != null && attrExt.size() > 0) {
//                straPreWarehouseCode = attrExt.getString("preWarehouseCode");
//            }
//
//            if (StringUtils.isEmpty(straPreWarehouseCode)) {
//                throw new BusinessException(ReturnCode.REQUEST_FAIL, "查询围栏对应的前置仓信息，为null");
//            }

//            // 策略服务与商城的数据比较
//            boolean flag = this.validateData(head.getOrderCode(), preWarehouseCode, straPreWarehouseCode, deliveryWay, straAttrInfo.getDeliveryWay());
//            if (!flag) {
//                throw new BusinessException(ReturnCode.REQUEST_FAIL, "前置仓信息、配送模式；策略服务返回，和商城不一致");
//            }

//            addressInfo.put("pre_warehouse_code", straPreWarehouseCode);
//            addressInfo.put("pre_warehouse_name", attrExt.get("preWarehouseName"));
//            addressInfo.put("isInDmall", straAttrInfo.getSecondDistributionFlag());
//            addressInfo.put("delivery_way", straAttrInfo.getDeliveryWay());
//            logger.info(logSign + "策略服务，前置仓号：{}, delivery_way：{}", straPreWarehouseCode, straAttrInfo.getDeliveryWay());
//            head.setAddressInfo(addressInfo.toJSONString());

//            return logisticsMode;
        } catch (BusinessException e) {
            throw e;
        }
    }

    /**
     * 解析经纬度坐标
     *
     * @param address
     * @return
     */
    public Position parsePosition(AddressInfo address) {
        Position position = null;
        JSONObject positionJson = JSON.parseObject(address.getPosition());
        if (positionJson != null && positionJson.size() != 0) {
            JSONObject userPosition = positionJson.getJSONObject("position");
            String lat = userPosition.getString("lat");
            String lng = userPosition.getString("lng");
            if (StringUtils.isNoneEmpty(lat, lng)) {
                position = new Position();
                position.setLat(lat);
                position.setLng(lng);
            }
        }

        return position;
    }

    private Double getOrderWeight(OrderHead head) {
        Double orderWeight = 6.66;
//        try {
//            orderWeight = this.calOrderWeight(head);
//        } catch (Exception ex) {
//            logger.error("请求进销存失败", ex);
//        }

        if (null == orderWeight) {
            orderWeight = 6.66;
        }
        logger.info("【{}】订单的重量是{}", head.getOrderCode(), orderWeight);

        return orderWeight;
    }

    /**
     * 计算订单重量
     *
     * @param dto
     * @return
     */
//    private Double calOrderWeight(OrderHead dto) {
//        Long orderCode = dto.getOrderCode();
//        if (dto.getParentOrderCode() != null && dto.getParentOrderCode().longValue() != 0L) {
//            orderCode = dto.getParentOrderCode();
//        }
//        Map<Long, Map<String, BigDecimal>> skuDcQtyMap = atpProxy.querySkuDcQtyInfo(orderCode);
//
//        Map<Long, BigDecimal> skuQty = new HashMap<>();
//        Map<String, Set<Long>> dcQtySkuCodesMap = new HashMap<>();
//        for (OrderDetail detail : dto.getDetails()) {
//            Long skuCode = detail.getSkuCode();
//            Long goodsCode = detail.getGoodsCode();
//            BigDecimal realQty = detail.getQuantity().multiply(detail.getGoodsSaleUnit());
//            if (skuQty.containsKey(goodsCode)) {
//                BigDecimal totalRealQty = skuQty.get(goodsCode).add(realQty);
//                skuQty.put(goodsCode, totalRealQty);
//            } else {
//                skuQty.put(goodsCode, realQty);
//            }
//
//            Map<String, BigDecimal> dcQtyMap = skuDcQtyMap.get(skuCode);
//            for (Map.Entry<String, BigDecimal> entry : dcQtyMap.entrySet()) {
//                Set<Long> goodsCodes = dcQtySkuCodesMap.get(entry.getKey());
//                if (com.lsh.base.common.utils.CollectionUtils.isEmpty(goodsCodes)) {
//                    goodsCodes = new HashSet<>();
//                    dcQtySkuCodesMap.put(entry.getKey(), goodsCodes);
//                }
//                goodsCodes.add(goodsCode);
//            }
//        }
//
//        Map<Long, Good> goodsInfoMap = new HashMap<>();
//        Map<String, BigDecimal> supplySkuCodeWeightMap = new HashMap<>();
//        for (Map.Entry<String, Set<Long>> entry : dcQtySkuCodesMap.entrySet()) {
//            String[] split = entry.getKey().split(":");
//            String dc = split[0];
//            Integer supplyMarket = Integer.valueOf(split[1]);
//            Integer supplyOrg = Integer.valueOf(split[2]);
//
//            Map<Long, Good> goodsInfo = GoodsServiceUtils.getGoodsInfoMapByGoodsCodes(shopUrl, entry.getValue(), supplyMarket, supplyOrg, dc, dto.getVenderId());
//
//            List<String> supplySkuCodeList = new ArrayList<>();
//            for (Map.Entry<Long, Good> goodsEntry : goodsInfo.entrySet()) {
//                Good good = goodsEntry.getValue();
//                supplySkuCodeList.add(good.getSupplySkuCode());
//            }
//            String supplySkuCodes = StringUtils.join(supplySkuCodeList.toArray(), ",");
//
//            Map<String, BigDecimal> goodsWeight;
//            if (SupplierOrg.LSH.getValue().equals(supplyOrg)) {
//                goodsWeight = wgServiceProxy.getGoodsWeight(supplySkuCodes, "2", dto.getVenderId());
//            } else if (SupplierOrg.WG.getValue().equals(supplyOrg)) {
//                goodsWeight = wgServiceProxy.getGoodsWeight(supplySkuCodes, "3", dto.getVenderId());
//            } else {
//                goodsWeight = Collections.emptyMap();
//            }
//
//            supplySkuCodeWeightMap.putAll(goodsWeight);
//            goodsInfoMap.putAll(goodsInfo);
//        }
//
//        BigDecimal totalWeight = BigDecimal.ZERO;
//        for (Map.Entry<Long, BigDecimal> entry : skuQty.entrySet()) {
//            Long goodCode = entry.getKey();
//            BigDecimal realQty = entry.getValue();
//            Good good = goodsInfoMap.get(goodCode);
//            BigDecimal weight = BigDecimal.ONE;
//            if (null != good) {
//                String supplySkuCode = good.getSupplySkuCode();
//
//                weight = supplySkuCodeWeightMap.get(supplySkuCode);
//                if (null == weight || weight.compareTo(BigDecimal.ZERO) <= 0) {
//                    weight = BigDecimal.ONE;
//                }
//            }
//            totalWeight = totalWeight.add(realQty.multiply(weight));
//        }
//        return totalWeight.doubleValue();
//    }

    /**
     * 用商城的信息，与策略服务返回的信息，作比较；不同，则报警
     *
     * @param orderCode
     * @param preWarehouseCode
     * @param straPreWarehouseCode
     * @param deliveryWay
     * @param straDeliveryWay
     */
    private boolean validateData(Long orderCode, String preWarehouseCode, String straPreWarehouseCode, Integer deliveryWay, Integer straDeliveryWay) {
        String dateFormat = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        if (!StringUtils.isEmpty(preWarehouseCode)) {
            if (!preWarehouseCode.equals(straPreWarehouseCode)) {
                String content = new StringBuilder("订单号：").append(orderCode).append("\n")
                        .append("preWarehouseCode和商城不一致，商城：").append(preWarehouseCode)
                        .append(", 策略服务：").append(straPreWarehouseCode).toString();
                sendEmailService.asyncSendEmail(content, "[oms]订单提交OFC,数据一致性问题-" + dateFormat, new String[]{"wangliutao@lsh123.com"});
                return false;
            }
        }
        if (deliveryWay != null) {
            if (deliveryWay.compareTo(straDeliveryWay) != 0) {
                String content = new StringBuilder("订单号：").append(orderCode).append("\n")
                        .append("delivery_way和商城不一致，商城：").append(deliveryWay)
                        .append(", 策略服务：").append(straDeliveryWay).toString();
                sendEmailService.asyncSendEmail(content, "[oms]订单提交OFC,数据一致性问题-" + dateFormat, new String[]{"wangliutao@lsh123.com"});
                return false;
            }
        }

        return true;
    }

    /**
     * 获取"围栏-前置仓"的对应关系
     *
     * @return
     */
    private String getPrewarehouseCode(String fenceId) {
        String prewarehouseCode = null;
        try {
            prewarehouseCode = redisTemplate.hget(FENCE_ID_PREWAREHOUSE_CODE_MAPPING, fenceId);
        } catch (Exception e) {
            logger.error("操作redis异常");
        }
        return prewarehouseCode;
    }

}
